#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>
#include <ctype.h>

#define N 128
#define MAX_FRAME_SIZE 1024

#define ERR_LOG(errmsg) do{\
                            perror(errmsg);\
	                    exit(1);\
                          }while(0)

// 将十六进制字符转换为数值
int hex_char_to_int(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    return -1;
}

// 将十六进制字符串转换为字节数组
int hex_string_to_bytes(const char* hex_str, unsigned char* bytes, int max_bytes) {
    int len = strlen(hex_str);
    int byte_count = 0;
    int i = 0;
    
    while (i < len && byte_count < max_bytes) {
        // 跳过分隔符
        while (i < len && (hex_str[i] == ' ' || hex_str[i] == ',' || 
                          hex_str[i] == '\t' || hex_str[i] == '\n' || 
                          hex_str[i] == '\r')) {
            i++;
        }
        
        if (i >= len) break;
        
        // 确保有两个有效的十六进制字符
        if (i + 1 < len) {
            int high = hex_char_to_int(hex_str[i]);
            int low = hex_char_to_int(hex_str[i + 1]);
            
            if (high >= 0 && low >= 0) {
                bytes[byte_count++] = (high << 4) | low;
                i += 2;
            } else {
                printf("错误：无效的十六进制字符 '%c%c' (位置: %d)\n", hex_str[i], hex_str[i + 1], i);
                return -1;
            }
        } else if (i < len) {
            // 处理最后一个单独的十六进制字符
            int val = hex_char_to_int(hex_str[i]);
            if (val >= 0) {
                bytes[byte_count++] = val;
                i++;
            } else {
                printf("错误：无效的十六进制字符 '%c' (位置: %d)\n", hex_str[i], i);
                return -1;
            }
        }
    }
    
    return byte_count;
}

// 打印字节数组为十六进制格式
void print_bytes_as_hex(const unsigned char* bytes, int len) {
    printf("发送的字节数据: ");
    for (int i = 0; i < len; i++) {
        printf("%02X ", bytes[i]);
    }
    printf("(共%d字节)\n", len);
}

int main(int argc, char const *argv[])
{
    // 输入参数：ip和端口
    if(argc < 3){
       fprintf(stderr,"Usage: %s [ip] [port]\n", argv[0]);
       exit(1);
    }

    int sockfd;
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
         ERR_LOG("fail to socket");
    }

    // 第二步：发送连接请求
    struct sockaddr_in serveraddr;
    socklen_t addrlen = sizeof(serveraddr);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));

    if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) == -1){
         ERR_LOG("fail to connect");
    }
    printf("连接成功!\n");
    printf("请输入十六进制数据，支持格式:\n");
    printf("  - 逗号分隔: A5,5A,01,00\n");
    printf("  - 空格分隔: A5 5A 01 00\n");
    printf("  - 连续格式: A55A0100\n");
    printf("  - 方括号格式: [A5,5A,01,00]\n");
    printf("输入 'quit' 退出\n");

    // 第三步: 通信
    char input_buf[N * 4] = "";  // 增大输入缓冲区
    unsigned char frame_data[MAX_FRAME_SIZE];
    
    while(1){
        printf("> ");
        fflush(stdout);
        
        // 读取用户输入
        if (fgets(input_buf, sizeof(input_buf), stdin) == NULL) {
            break;
        }
        
        // 移除换行符
        int input_len = strlen(input_buf);
        if (input_len > 0 && input_buf[input_len - 1] == '\n') {
            input_buf[input_len - 1] = '\0';
        }

        // 检查退出命令
        if(strncmp(input_buf, "quit", 4) == 0){
            break;
        }
        
        // 跳过空输入
        if (strlen(input_buf) == 0) {
            continue;
        }

        // 将十六进制字符串转换为字节数组
        int frame_len = hex_string_to_bytes(input_buf, frame_data, MAX_FRAME_SIZE);
        if (frame_len <= 0) {
            printf("输入格式错误，请输入有效的十六进制数据\n");
            continue;
        }

        // 显示要发送的数据
        print_bytes_as_hex(frame_data, frame_len);

        // 发送字节数据
        if(send(sockfd, frame_data, frame_len, 0) < 0){
            ERR_LOG("fail to send");
        }

        // 设置接收超时（5秒）
        struct timeval timeout;
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

        // 接收回复
        unsigned char recv_buf[MAX_FRAME_SIZE];
        int recv_len = recv(sockfd, recv_buf, MAX_FRAME_SIZE, 0);
        
        if(recv_len < 0){
            printf("接收数据超时或出错\n");
        } else if (recv_len == 0) {
            printf("服务器关闭了连接\n");
            break;
        } else {
            printf("收到回复 (%d字节): ", recv_len);
            for (int i = 0; i < recv_len; i++) {
                printf("%02X ", recv_buf[i]);
            }
            printf("\n");
        }
    }    

    // 关闭连接
    close(sockfd);
    printf("连接已关闭\n");
    return 0;
}